#!/usr/bin/env python3
import sys
import asyncio
import urllib.parse
import json


async def get_json(url):
    # unfortunately Python doesn't come with a builtin async HTTP client
    url = urllib.parse.urlsplit(url)
    query = (f"GET {url.path}?{url.query} HTTP/1.0\r\nHost: {url.hostname}\r\n\r\n")
    reader, writer = await asyncio.open_connection(url.hostname, url.port)

    writer.write(query.encode('latin-1'))
    response = await reader.read()
    response = response.decode('latin-1')
    _headers, content = response.split('\r\n\r\n', maxsplit=1)
    writer.close()
    return json.loads(content)


async def context_and_fetch(host: str, port: int):
    ctx = await get_json(f"http://{host}:{port}/pmapi/context?hostspec=127.0.0.1&polltimeout=30")
    ctx_id = ctx["context"]
    metric = await get_json(f"http://{host}:{port}/pmapi/{ctx_id}/fetch?names=disk.dev.read")
    inst_val = metric["values"][0]["instances"][0]["value"]
    if not inst_val:
        raise Exception("cannot find any instance value for disk.dev.read")
    return inst_val


async def main(count):
    print(f"Sending {count} /context and /fetch requests...")
    responses = await asyncio.gather(
        *[context_and_fetch("localhost", "44322") for i in range(count)],
        return_exceptions=True
    )
    succeed = sum(1 for response in responses if isinstance(response, int))
    percentage = round(succeed/count*100)
    print(f"Successful responses: {succeed}/{count} ({percentage}%)")
    if succeed < count:
        print("\nThe following exceptions occured:")
        for response in responses:
            if isinstance(response, Exception):
                print(response)

if __name__ == '__main__':
    if len(sys.argv) != 2:
        print(f"usage: {sys.argv[0]} COUNT")
        sys.exit(1)

    event_loop = asyncio.get_event_loop()
    event_loop.run_until_complete(main(int(sys.argv[1])))
    event_loop.close()
